1   /*
2    * Copyright (C) 2009 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.base;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  import com.google.common.annotations.GwtIncompatible;
23  import com.google.common.collect.ImmutableList;
24  import com.google.common.collect.ImmutableMap;
25  import com.google.common.testing.NullPointerTester;
26  
27  import junit.framework.TestCase;
28  
29  import java.util.Collection;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.regex.Pattern;
34  
35  /**
36   * @author Julien Silland
37   */
38  @GwtCompatible(emulated = true)
39  public class SplitterTest extends TestCase {
40  
41    private static final Splitter COMMA_SPLITTER = Splitter.on(',');
42  
43    public void testSplitNullString() {
44      try {
45        COMMA_SPLITTER.split(null);
46        fail();
47      } catch (NullPointerException expected) {
48      }
49    }
50  
51    public void testCharacterSimpleSplit() {
52      String simple = "a,b,c";
53      Iterable<String> letters = COMMA_SPLITTER.split(simple);
54      assertThat(letters).iteratesAs("a", "b", "c");
55    }
56  
57    /**
58     * All of the infrastructure of split and splitToString is identical, so we
59     * do one test of splitToString. All other cases should be covered by testing
60     * of split.
61     *
62     * <p>TODO(user): It would be good to make all the relevant tests run on
63     * both split and splitToString automatically.
64     */
65    public void testCharacterSimpleSplitToList() {
66      String simple = "a,b,c";
67      List<String> letters = COMMA_SPLITTER.splitToList(simple);
68      assertThat(letters).iteratesAs("a", "b", "c");
69    }
70  
71    public void testToString() {
72      assertEquals("[]", Splitter.on(',').split("").toString());
73      assertEquals("[a, b, c]", Splitter.on(',').split("a,b,c").toString());
74      assertEquals("[yam, bam, jam, ham]", Splitter.on(", ").split("yam, bam, jam, ham").toString());
75    }
76  
77    public void testCharacterSimpleSplitWithNoDelimiter() {
78      String simple = "a,b,c";
79      Iterable<String> letters = Splitter.on('.').split(simple);
80      assertThat(letters).iteratesAs("a,b,c");
81    }
82  
83    public void testCharacterSplitWithDoubleDelimiter() {
84      String doubled = "a,,b,c";
85      Iterable<String> letters = COMMA_SPLITTER.split(doubled);
86      assertThat(letters).iteratesAs("a", "", "b", "c");
87    }
88  
89    public void testCharacterSplitWithDoubleDelimiterAndSpace() {
90      String doubled = "a,, b,c";
91      Iterable<String> letters = COMMA_SPLITTER.split(doubled);
92      assertThat(letters).iteratesAs("a", "", " b", "c");
93    }
94  
95    public void testCharacterSplitWithTrailingDelimiter() {
96      String trailing = "a,b,c,";
97      Iterable<String> letters = COMMA_SPLITTER.split(trailing);
98      assertThat(letters).iteratesAs("a", "b", "c", "");
99    }
100 
101   public void testCharacterSplitWithLeadingDelimiter() {
102     String leading = ",a,b,c";
103     Iterable<String> letters = COMMA_SPLITTER.split(leading);
104     assertThat(letters).iteratesAs("", "a", "b", "c");
105   }
106 
107   public void testCharacterSplitWithMulitpleLetters() {
108     Iterable<String> testCharacteringMotto = Splitter.on('-').split(
109         "Testing-rocks-Debugging-sucks");
110     assertThat(testCharacteringMotto).iteratesAs(
111         "Testing", "rocks", "Debugging", "sucks");
112   }
113 
114   public void testCharacterSplitWithMatcherDelimiter() {
115     Iterable<String> testCharacteringMotto = Splitter
116         .on(CharMatcher.WHITESPACE)
117         .split("Testing\nrocks\tDebugging sucks");
118     assertThat(testCharacteringMotto).iteratesAs(
119         "Testing", "rocks", "Debugging", "sucks");
120   }
121 
122   public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
123     String doubled = "a..b.c";
124     Iterable<String> letters = Splitter.on('.')
125         .omitEmptyStrings().split(doubled);
126     assertThat(letters).iteratesAs("a", "b", "c");
127   }
128 
129   public void testCharacterSplitEmptyToken() {
130     String emptyToken = "a. .c";
131     Iterable<String> letters = Splitter.on('.').trimResults()
132         .split(emptyToken);
133     assertThat(letters).iteratesAs("a", "", "c");
134   }
135 
136   public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
137     String emptyToken = "a. .c";
138     Iterable<String> letters = Splitter.on('.')
139         .omitEmptyStrings().trimResults().split(emptyToken);
140     assertThat(letters).iteratesAs("a", "c");
141   }
142 
143   public void testCharacterSplitOnEmptyString() {
144     Iterable<String> nothing = Splitter.on('.').split("");
145     assertThat(nothing).iteratesAs("");
146   }
147 
148   public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
149     assertThat(Splitter.on('.').omitEmptyStrings().split("")).isEmpty();
150   }
151 
152   public void testCharacterSplitOnOnlyDelimiter() {
153     Iterable<String> blankblank = Splitter.on('.').split(".");
154     assertThat(blankblank).iteratesAs("", "");
155   }
156 
157   public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
158     Iterable<String> empty = Splitter.on('.').omitEmptyStrings().split("...");
159     assertThat(empty).isEmpty();
160   }
161 
162   public void testCharacterSplitWithTrim() {
163     String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
164         + "ofar(Jemaine), aff(Tito)";
165     Iterable<String> family = COMMA_SPLITTER
166         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
167         .split(jacksons);
168     assertThat(family).iteratesAs(
169         "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
170   }
171 
172   public void testStringSimpleSplit() {
173     String simple = "a,b,c";
174     Iterable<String> letters = Splitter.on(',').split(simple);
175     assertThat(letters).iteratesAs("a", "b", "c");
176   }
177 
178   public void testStringSimpleSplitWithNoDelimiter() {
179     String simple = "a,b,c";
180     Iterable<String> letters = Splitter.on('.').split(simple);
181     assertThat(letters).iteratesAs("a,b,c");
182   }
183 
184   public void testStringSplitWithDoubleDelimiter() {
185     String doubled = "a,,b,c";
186     Iterable<String> letters = Splitter.on(',').split(doubled);
187     assertThat(letters).iteratesAs("a", "", "b", "c");
188   }
189 
190   public void testStringSplitWithDoubleDelimiterAndSpace() {
191     String doubled = "a,, b,c";
192     Iterable<String> letters = Splitter.on(',').split(doubled);
193     assertThat(letters).iteratesAs("a", "", " b", "c");
194   }
195 
196   public void testStringSplitWithTrailingDelimiter() {
197     String trailing = "a,b,c,";
198     Iterable<String> letters = Splitter.on(',').split(trailing);
199     assertThat(letters).iteratesAs("a", "b", "c", "");
200   }
201 
202   public void testStringSplitWithLeadingDelimiter() {
203     String leading = ",a,b,c";
204     Iterable<String> letters = Splitter.on(',').split(leading);
205     assertThat(letters).iteratesAs("", "a", "b", "c");
206   }
207 
208   public void testStringSplitWithMultipleLetters() {
209     Iterable<String> testStringingMotto = Splitter.on('-').split(
210         "Testing-rocks-Debugging-sucks");
211     assertThat(testStringingMotto).iteratesAs(
212         "Testing", "rocks", "Debugging", "sucks");
213   }
214 
215   public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
216     String doubled = "a..b.c";
217     Iterable<String> letters = Splitter.on('.')
218         .omitEmptyStrings().split(doubled);
219     assertThat(letters).iteratesAs("a", "b", "c");
220   }
221 
222   public void testStringSplitEmptyToken() {
223     String emptyToken = "a. .c";
224     Iterable<String> letters = Splitter.on('.').trimResults()
225         .split(emptyToken);
226     assertThat(letters).iteratesAs("a", "", "c");
227   }
228 
229   public void testStringSplitEmptyTokenOmitEmptyStrings() {
230     String emptyToken = "a. .c";
231     Iterable<String> letters = Splitter.on('.')
232         .omitEmptyStrings().trimResults().split(emptyToken);
233     assertThat(letters).iteratesAs("a", "c");
234   }
235 
236   public void testStringSplitWithLongDelimiter() {
237     String longDelimiter = "a, b, c";
238     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
239     assertThat(letters).iteratesAs("a", "b", "c");
240   }
241 
242   public void testStringSplitWithLongLeadingDelimiter() {
243     String longDelimiter = ", a, b, c";
244     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
245     assertThat(letters).iteratesAs("", "a", "b", "c");
246   }
247 
248   public void testStringSplitWithLongTrailingDelimiter() {
249     String longDelimiter = "a, b, c, ";
250     Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
251     assertThat(letters).iteratesAs("a", "b", "c", "");
252   }
253 
254   public void testStringSplitWithDelimiterSubstringInValue() {
255     String fourCommasAndFourSpaces = ",,,,    ";
256     Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
257         fourCommasAndFourSpaces);
258     assertThat(threeCommasThenThreeSpaces).iteratesAs(",,,", "   ");
259   }
260 
261   public void testStringSplitWithEmptyString() {
262     try {
263       Splitter.on("");
264       fail();
265     } catch (IllegalArgumentException expected) {
266     }
267   }
268 
269   public void testStringSplitOnEmptyString() {
270     Iterable<String> notMuch = Splitter.on('.').split("");
271     assertThat(notMuch).iteratesAs("");
272   }
273 
274   public void testStringSplitOnEmptyStringOmitEmptyString() {
275     assertThat(Splitter.on('.').omitEmptyStrings().split("")).isEmpty();
276   }
277 
278   public void testStringSplitOnOnlyDelimiter() {
279     Iterable<String> blankblank = Splitter.on('.').split(".");
280     assertThat(blankblank).iteratesAs("", "");
281   }
282 
283   public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
284     Iterable<String> empty = Splitter.on('.').omitEmptyStrings().split("...");
285     assertThat(empty).isEmpty();
286   }
287 
288   public void testStringSplitWithTrim() {
289     String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
290         + "ofar(Jemaine), aff(Tito)";
291     Iterable<String> family = Splitter.on(',')
292         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
293         .split(jacksons);
294     assertThat(family).iteratesAs(
295         "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
296   }
297 
298   @GwtIncompatible("Splitter.onPattern")
299   public void testPatternSimpleSplit() {
300     String simple = "a,b,c";
301     Iterable<String> letters = Splitter.onPattern(",").split(simple);
302     assertThat(letters).iteratesAs("a", "b", "c");
303   }
304 
305   @GwtIncompatible("Splitter.onPattern")
306   public void testPatternSimpleSplitWithNoDelimiter() {
307     String simple = "a,b,c";
308     Iterable<String> letters = Splitter.onPattern("foo").split(simple);
309     assertThat(letters).iteratesAs("a,b,c");
310   }
311 
312   @GwtIncompatible("Splitter.onPattern")
313   public void testPatternSplitWithDoubleDelimiter() {
314     String doubled = "a,,b,c";
315     Iterable<String> letters = Splitter.onPattern(",").split(doubled);
316     assertThat(letters).iteratesAs("a", "", "b", "c");
317   }
318 
319   @GwtIncompatible("Splitter.onPattern")
320   public void testPatternSplitWithDoubleDelimiterAndSpace() {
321     String doubled = "a,, b,c";
322     Iterable<String> letters = Splitter.onPattern(",").split(doubled);
323     assertThat(letters).iteratesAs("a", "", " b", "c");
324   }
325 
326   @GwtIncompatible("Splitter.onPattern")
327   public void testPatternSplitWithTrailingDelimiter() {
328     String trailing = "a,b,c,";
329     Iterable<String> letters = Splitter.onPattern(",").split(trailing);
330     assertThat(letters).iteratesAs("a", "b", "c", "");
331   }
332 
333   @GwtIncompatible("Splitter.onPattern")
334   public void testPatternSplitWithLeadingDelimiter() {
335     String leading = ",a,b,c";
336     Iterable<String> letters = Splitter.onPattern(",").split(leading);
337     assertThat(letters).iteratesAs("", "a", "b", "c");
338   }
339 
340   // TODO(kevinb): the name of this method suggests it might not actually be testing what it
341   // intends to be testing?
342   @GwtIncompatible("Splitter.onPattern")
343   public void testPatternSplitWithMultipleLetters() {
344     Iterable<String> testPatterningMotto = Splitter.onPattern("-").split(
345         "Testing-rocks-Debugging-sucks");
346     assertThat(testPatterningMotto).iteratesAs("Testing", "rocks", "Debugging", "sucks");
347   }
348 
349   @GwtIncompatible("java.util.regex.Pattern")
350   private static Pattern literalDotPattern() {
351     return Pattern.compile("\\.");
352   }
353 
354   @GwtIncompatible("java.util.regex.Pattern")
355   public void testPatternSplitWithDoubleDelimiterOmitEmptyStrings() {
356     String doubled = "a..b.c";
357     Iterable<String> letters = Splitter.on(literalDotPattern())
358         .omitEmptyStrings().split(doubled);
359     assertThat(letters).iteratesAs("a", "b", "c");
360   }
361 
362   @GwtIncompatible("java.util.regex.Pattern")
363   public void testPatternSplitLookBehind() {
364     String toSplit = ":foo::barbaz:";
365     String regexPattern = "(?<=:)";
366     Iterable<String> split = Splitter.onPattern(regexPattern).split(toSplit);
367     assertThat(split).iteratesAs(":", "foo:", ":", "barbaz:");
368     // splits into chunks ending in :
369   }
370 
371   @GwtIncompatible("java.util.regex.Pattern")
372   public void testPatternSplitWordBoundary() {
373     String string = "foo<bar>bletch";
374     Iterable<String> words = Splitter.on(Pattern.compile("\\b")).split(string);
375     assertThat(words).iteratesAs("foo", "<", "bar", ">", "bletch");
376   }
377 
378   @GwtIncompatible("java.util.regex.Pattern")
379   public void testPatternSplitEmptyToken() {
380     String emptyToken = "a. .c";
381     Iterable<String> letters = Splitter.on(literalDotPattern()).trimResults().split(emptyToken);
382     assertThat(letters).iteratesAs("a", "", "c");
383   }
384 
385   @GwtIncompatible("java.util.regex.Pattern")
386   public void testPatternSplitEmptyTokenOmitEmptyStrings() {
387     String emptyToken = "a. .c";
388     Iterable<String> letters = Splitter.on(literalDotPattern())
389         .omitEmptyStrings().trimResults().split(emptyToken);
390     assertThat(letters).iteratesAs("a", "c");
391   }
392 
393   @GwtIncompatible("java.util.regex.Pattern")
394   public void testPatternSplitOnOnlyDelimiter() {
395     Iterable<String> blankblank = Splitter.on(literalDotPattern()).split(".");
396 
397     assertThat(blankblank).iteratesAs("", "");
398   }
399 
400   @GwtIncompatible("java.util.regex.Pattern")
401   public void testPatternSplitOnOnlyDelimitersOmitEmptyStrings() {
402     Iterable<String> empty = Splitter.on(literalDotPattern()).omitEmptyStrings()
403         .split("...");
404     assertThat(empty).isEmpty();
405   }
406 
407   @GwtIncompatible("java.util.regex.Pattern")
408   public void testPatternSplitMatchingIsGreedy() {
409     String longDelimiter = "a, b,   c";
410     Iterable<String> letters = Splitter.on(Pattern.compile(",\\s*"))
411         .split(longDelimiter);
412     assertThat(letters).iteratesAs("a", "b", "c");
413   }
414 
415   @GwtIncompatible("java.util.regex.Pattern")
416   public void testPatternSplitWithLongLeadingDelimiter() {
417     String longDelimiter = ", a, b, c";
418     Iterable<String> letters = Splitter.on(Pattern.compile(", "))
419         .split(longDelimiter);
420     assertThat(letters).iteratesAs("", "a", "b", "c");
421   }
422 
423   @GwtIncompatible("java.util.regex.Pattern")
424   public void testPatternSplitWithLongTrailingDelimiter() {
425     String longDelimiter = "a, b, c/ ";
426     Iterable<String> letters = Splitter.on(Pattern.compile("[,/]\\s"))
427         .split(longDelimiter);
428     assertThat(letters).iteratesAs("a", "b", "c", "");
429   }
430 
431   @GwtIncompatible("java.util.regex.Pattern")
432   public void testPatternSplitInvalidPattern() {
433     try {
434       Splitter.on(Pattern.compile("a*"));
435       fail();
436     } catch (IllegalArgumentException expected) {
437     }
438   }
439 
440   @GwtIncompatible("java.util.regex.Pattern")
441   public void testPatternSplitWithTrim() {
442     String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
443         + "ofar(Jemaine), aff(Tito)";
444     Iterable<String> family = Splitter.on(Pattern.compile(","))
445         .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
446         .split(jacksons);
447     assertThat(family).iteratesAs(
448         "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
449   }
450 
451   public void testSplitterIterableIsUnmodifiable_char() {
452     assertIteratorIsUnmodifiable(COMMA_SPLITTER.split("a,b").iterator());
453   }
454 
455   public void testSplitterIterableIsUnmodifiable_string() {
456     assertIteratorIsUnmodifiable(Splitter.on(',').split("a,b").iterator());
457   }
458 
459   @GwtIncompatible("java.util.regex.Pattern")
460   public void testSplitterIterableIsUnmodifiable_pattern() {
461     assertIteratorIsUnmodifiable(
462         Splitter.on(Pattern.compile(",")).split("a,b").iterator());
463   }
464 
465   private void assertIteratorIsUnmodifiable(Iterator<?> iterator) {
466     iterator.next();
467     try {
468       iterator.remove();
469       fail();
470     } catch (UnsupportedOperationException expected) {
471     }
472   }
473 
474   public void testSplitterIterableIsLazy_char() {
475     assertSplitterIterableIsLazy(COMMA_SPLITTER);
476   }
477 
478   public void testSplitterIterableIsLazy_string() {
479     assertSplitterIterableIsLazy(Splitter.on(','));
480   }
481 
482   @GwtIncompatible("java.util.regex.Pattern")
483   public void testSplitterIterableIsLazy_pattern() {
484     assertSplitterIterableIsLazy(Splitter.onPattern(","));
485   }
486 
487   /**
488    * This test really pushes the boundaries of what we support. In general the
489    * splitter's behaviour is not well defined if the char sequence it's
490    * splitting is mutated during iteration.
491    */
492   private void assertSplitterIterableIsLazy(Splitter splitter) {
493     StringBuilder builder = new StringBuilder();
494     Iterator<String> iterator = splitter.split(builder).iterator();
495 
496     builder.append("A,");
497     assertEquals("A", iterator.next());
498     builder.append("B,");
499     assertEquals("B", iterator.next());
500     builder.append("C");
501     assertEquals("C", iterator.next());
502     assertFalse(iterator.hasNext());
503   }
504 
505   public void testFixedLengthSimpleSplit() {
506     String simple = "abcde";
507     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
508     assertThat(letters).iteratesAs("ab", "cd", "e");
509   }
510 
511   public void testFixedLengthSplitEqualChunkLength() {
512     String simple = "abcdef";
513     Iterable<String> letters = Splitter.fixedLength(2).split(simple);
514     assertThat(letters).iteratesAs("ab", "cd", "ef");
515   }
516 
517   public void testFixedLengthSplitOnlyOneChunk() {
518     String simple = "abc";
519     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
520     assertThat(letters).iteratesAs("abc");
521   }
522 
523   public void testFixedLengthSplitSmallerString() {
524     String simple = "ab";
525     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
526     assertThat(letters).iteratesAs("ab");
527   }
528 
529   public void testFixedLengthSplitEmptyString() {
530     String simple = "";
531     Iterable<String> letters = Splitter.fixedLength(3).split(simple);
532     assertThat(letters).iteratesAs("");
533   }
534 
535   public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
536     assertThat(Splitter.fixedLength(3).omitEmptyStrings().split("")).isEmpty();
537   }
538 
539   public void testFixedLengthSplitIntoChars() {
540     String simple = "abcd";
541     Iterable<String> letters = Splitter.fixedLength(1).split(simple);
542     assertThat(letters).iteratesAs("a", "b", "c", "d");
543   }
544 
545   public void testFixedLengthSplitZeroChunkLen() {
546     try {
547       Splitter.fixedLength(0);
548       fail();
549     } catch (IllegalArgumentException expected) {
550     }
551   }
552 
553   public void testFixedLengthSplitNegativeChunkLen() {
554     try {
555       Splitter.fixedLength(-1);
556       fail();
557     } catch (IllegalArgumentException expected) {
558     }
559   }
560 
561   public void testLimitLarge() {
562     String simple = "abcd";
563     Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
564     assertThat(letters).iteratesAs("a", "b", "c", "d");
565   }
566 
567   public void testLimitOne() {
568     String simple = "abcd";
569     Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
570     assertThat(letters).iteratesAs("abcd");
571   }
572 
573   public void testLimitFixedLength() {
574     String simple = "abcd";
575     Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
576     assertThat(letters).iteratesAs("a", "bcd");
577   }
578 
579   public void testLimitSeparator() {
580     String simple = "a,b,c,d";
581     Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
582     assertThat(items).iteratesAs("a", "b,c,d");
583   }
584 
585   public void testLimitExtraSeparators() {
586     String text = "a,,,b,,c,d";
587     Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
588     assertThat(items).iteratesAs("a", ",,b,,c,d");
589   }
590 
591   public void testLimitExtraSeparatorsOmitEmpty() {
592     String text = "a,,,b,,c,d";
593     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
594     assertThat(items).iteratesAs("a", "b,,c,d");
595   }
596 
597   public void testLimitExtraSeparatorsOmitEmpty3() {
598     String text = "a,,,b,,c,d";
599     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
600     assertThat(items).iteratesAs("a", "b", "c,d");
601   }
602 
603   public void testLimitExtraSeparatorsTrim() {
604     String text = ",,a,,  , b ,, c,d ";
605     Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
606     assertThat(items).iteratesAs("a", "b ,, c,d");
607   }
608 
609   public void testLimitExtraSeparatorsTrim3() {
610     String text = ",,a,,  , b ,, c,d ";
611     Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
612     assertThat(items).iteratesAs("a", "b", "c,d");
613   }
614 
615   public void testLimitExtraSeparatorsTrim1() {
616     String text = ",,a,,  , b ,, c,d ";
617     Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
618     assertThat(items).iteratesAs("a,,  , b ,, c,d");
619   }
620 
621   public void testLimitExtraSeparatorsTrim1NoOmit() {
622     String text = ",,a,,  , b ,, c,d ";
623     Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
624     assertThat(items).iteratesAs(",,a,,  , b ,, c,d");
625   }
626 
627   public void testLimitExtraSeparatorsTrim1Empty() {
628     String text = "";
629     Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
630     assertThat(items).iteratesAs("");
631   }
632 
633   public void testLimitExtraSeparatorsTrim1EmptyOmit() {
634     String text = "";
635     Iterable<String> items = COMMA_SPLITTER.omitEmptyStrings().limit(1).split(text);
636     assertThat(items).isEmpty();
637   }
638 
639   @SuppressWarnings("ReturnValueIgnored") // testing for exception
640   public void testInvalidZeroLimit() {
641     try {
642       COMMA_SPLITTER.limit(0);
643       fail();
644     } catch (IllegalArgumentException expected) {
645     }
646   }
647 
648   @GwtIncompatible("NullPointerTester")
649   public void testNullPointers() {
650     NullPointerTester tester = new NullPointerTester();
651     tester.testAllPublicStaticMethods(Splitter.class);
652     tester.testAllPublicInstanceMethods(Splitter.on(','));
653     tester.testAllPublicInstanceMethods(Splitter.on(',').trimResults());
654   }
655 
656   private static <E> List<E> asList(Collection<E> collection) {
657     return ImmutableList.copyOf(collection);
658   }
659 
660   public void testMapSplitter_trimmedBoth() {
661     Map<String, String> m = COMMA_SPLITTER
662         .trimResults()
663         .withKeyValueSeparator(Splitter.on(':').trimResults())
664         .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
665     ImmutableMap<String, String> expected =
666           ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
667     assertThat(m).isEqualTo(expected);
668     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
669   }
670 
671   public void testMapSplitter_trimmedEntries() {
672     Map<String, String> m = COMMA_SPLITTER
673         .trimResults()
674         .withKeyValueSeparator(":")
675         .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
676     ImmutableMap<String, String> expected =
677         ImmutableMap.of("boy  ", " tom", "girl", " tina", "cat  ", " kitty", "dog", " tommy");
678 
679     assertThat(m).isEqualTo(expected);
680     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
681   }
682 
683   public void testMapSplitter_trimmedKeyValue() {
684     Map<String, String> m =
685         COMMA_SPLITTER.withKeyValueSeparator(Splitter.on(':').trimResults()).split(
686             "boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
687     ImmutableMap<String, String> expected =
688         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
689     assertThat(m).isEqualTo(expected);
690     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
691   }
692 
693   public void testMapSplitter_notTrimmed() {
694     Map<String, String> m = COMMA_SPLITTER.withKeyValueSeparator(":").split(
695         " boy:tom , girl: tina , cat :kitty , dog:  tommy ");
696     ImmutableMap<String, String> expected =
697         ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", "  tommy ");
698     assertThat(m).isEqualTo(expected);
699     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
700   }
701 
702   public void testMapSplitter_CharacterSeparator() {
703     // try different delimiters.
704     Map<String, String> m = Splitter
705         .on(",")
706         .withKeyValueSeparator(':')
707         .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
708     ImmutableMap<String, String> expected =
709         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
710 
711     assertThat(m).isEqualTo(expected);
712     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
713   }
714 
715   public void testMapSplitter_multiCharacterSeparator() {
716     // try different delimiters.
717     Map<String, String> m = Splitter
718         .on(",")
719         .withKeyValueSeparator(":^&")
720         .split("boy:^&tom,girl:^&tina,cat:^&kitty,dog:^&tommy");
721     ImmutableMap<String, String> expected =
722         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
723 
724     assertThat(m).isEqualTo(expected);
725     assertThat(asList(m.entrySet())).isEqualTo(asList(expected.entrySet()));
726   }
727 
728   @SuppressWarnings("ReturnValueIgnored") // testing for exception
729   public void testMapSplitter_emptySeparator() {
730     try {
731       COMMA_SPLITTER.withKeyValueSeparator("");
732       fail();
733     } catch (IllegalArgumentException expected) {
734     }
735   }
736 
737   public void testMapSplitter_malformedEntry() {
738     try {
739       COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
740       fail();
741     } catch (IllegalArgumentException expected) {
742     }
743   }
744 
745   public void testMapSplitter_orderedResults() {
746     Map<String, String> m = Splitter.on(',')
747         .withKeyValueSeparator(":")
748         .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
749 
750     assertThat(m.keySet()).iteratesAs("boy", "girl", "cat", "dog");
751     assertThat(m).isEqualTo(
752         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
753 
754     // try in a different order
755     m = Splitter.on(',')
756         .withKeyValueSeparator(":")
757         .split("girl:tina,boy:tom,dog:tommy,cat:kitty");
758 
759     assertThat(m.keySet()).iteratesAs("girl", "boy", "dog", "cat");
760     assertThat(m).isEqualTo(
761         ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
762   }
763 
764   public void testMapSplitter_duplicateKeys() {
765     try {
766       Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
767       fail();
768     } catch (IllegalArgumentException expected) {
769     }
770   }
771 }